home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / c / tde31.zip / SIMUL101.ASM < prev    next >
Assembly Source File  |  1993-08-29  |  14KB  |  323 lines

  1. ;
  2. ; This function simulates the scan codes of the 101 keyboard on older 83/84 key
  3. ; keyboard systems that lack bios support for some often used 101 keyboard
  4. ; control key combinations.  I miss being able to use the Control+Up, which is
  5. ; one of the key combinations that the old BIOS does not support on my old
  6. ; machine at home.  Not all of the 101 keys are simulated.
  7. ;
  8. ; To see if control+up is pressed, we have to look at the keyboard status flags
  9. ; in the bios data area.  The flags at byte 0040:0017 are as follows:
  10. ;
  11. ;   Bit
  12. ;    7   Insert state  1 = active,  0 = inactive
  13. ;    6   Caps Lock     1 = active,  0 = inactive
  14. ;    5   Num Lock      1 = active,  0 = inactive
  15. ;    4   Scroll Lock   1 = active,  0 = inactive
  16. ;    3   Alt Shift     1 = active,  0 = inactive
  17. ;    2   Ctrl Shift    1 = active,  0 = inactive
  18. ;    1   Left Shift    1 = active,  0 = inactive
  19. ;    0   Right Shift   1 = active,  0 = inactive
  20. ;
  21. ; We are only concerned with bits 0-3, the shift status bits.  At label "k1"
  22. ; in this routine, the status byte is tested with 0x0f.  With simple tests,
  23. ; the status of the shift keys can be determined.  Then, it easy to use the
  24. ; tables to translate (XLAT) the raw key codes to extended scan codes.
  25. ;
  26. ; This function was designed to be linked with C object code.  The prototype
  27. ; for this function is far so it may be easily used with any memory model.
  28. ;
  29. ; For those of you (like me) who use keyboard speed up or other keyboard TSRs
  30. ; on XT's, you will find that those TSRs do not work with simulated scan codes
  31. ; generated by this utility.  This function grabs the raw keys before the TSR
  32. ; gets them and they don't get passed to the TSR.  This is the reason I mapped
  33. ; the "Keypad -" and "Keypad +" to the scroll up and scroll down functions -
  34. ; they aren't filtered by this function and get through to the typefast (TSR)
  35. ; utilities, so you can scroll really fast thru files.
  36. ;
  37. ; See:
  38. ;
  39. ;   Technical Reference for the Personal Computer AT, IBM Corporation,
  40. ;      Boca Raton, Florida, USA., 1984, First Edition (March 1984),
  41. ;      IBM part no. 1502243 and 1502494, pp. 1-31 thru 1-43,
  42. ;      pp. 4-1 thru 4-24, pp. 5-27 thru 5-32, pp. 5-115 thru 5-121, and
  43. ;      pp. 5-169 thru 5-170.
  44. ;
  45. ;   Microsoft Macro Assembler, Version 6.0, Reference, Microsoft Corporation,
  46. ;      Redmond, Washington, 1991, Document No. LN06557-0291, pp 194-195.
  47. ;
  48. ;   User's Guide and Reference for the MS-DOS Operating System, Version 5.0,
  49. ;      Microsoft Corporation, Redmond, Washington, 1991,
  50. ;      Document No. SY07661/20885-0391, pp. 623-637.
  51. ;
  52. ;
  53. ; Assembler flags:
  54. ;
  55. ;      QuickAssembler:   qcl /c simul101.asm
  56. ;            MASM 6.0:   ml /c /Cp /Zm simul101.asm
  57. ;
  58. ; Editor name:   TDE, the Thomson-Davis Editor.
  59. ; Author:        Frank Davis
  60. ; Date:          June 5, 1991, version 1.0
  61. ; Date:          July 29, 1991, version 1.1
  62. ; Date:          October 5, 1991, version 1.2
  63. ; Date:          January 20, 1992, version 1.3
  64. ; Date:          February 17, 1992, version 1.4
  65. ; Date:          April 1, 1992, version 1.5
  66. ; Date:          June 5, 1992, version 2.0
  67. ; Date:          October 31, 1992, version 2.1
  68. ;
  69. ; This code is released into the public domain, Frank Davis.  You may
  70. ; distribute it freely.
  71.  
  72. kb_data_port    EQU     60h
  73. kb_cntl_port    EQU     61h
  74.  
  75. bios_data       SEGMENT AT 40h
  76.                 ORG     17h
  77. kb_status       DB      ?
  78.                 ORG     1ah
  79. buffer_head     DW      ?
  80. buffer_tail     DW      ?
  81.                 ORG     80h
  82. buffer_start    DW      ?
  83. buffer_end      DW      ?
  84. bios_data       ENDS
  85.  
  86.  
  87. _TEXT   SEGMENT WORD PUBLIC 'CODE'
  88.         ASSUME  cs:_TEXT, ds:NOTHING, es:bios_data
  89.         public  _simulate_enh_kbd
  90.  
  91.  
  92. ;
  93. ; Prototype this function as far in the C header file so it may be used easily
  94. ; with any memory model.  See the last section in tdefunc.h for more info.
  95. ;
  96. _simulate_enh_kbd       PROC    FAR
  97.         jmp     initialize
  98.  
  99.  
  100. ; Map the keys starting at scan code 47h, which is the Home key.  This routine
  101. ; DOES NOT return most of these values from systems with a 101 enhanced keyboard
  102. ; connected, but the codes are included here for reference.  One should use the
  103. ; extended BIOS keyboard services with the 101 keyboard and not this function.
  104. ; Indeed, tde uses the extended BIOS if a 101 keyboard is detected.
  105. ;
  106. ; These tables are patterned after the ones in the IBM AT Technical Reference
  107. ; Manual, page 5-170 (the system bios listing), labels k8 thru k15.
  108. ;
  109. ;       Home   = 47h    Left   = 4bh    End   = 4fh    Del    = 53h   F11 = 57h
  110. ;       Up     = 48h    Center = 4ch    Down  = 50h    SysReq = 54h   F12 = 58h
  111. ;       PgUp   = 49h    Right  = 4dh    PgDn  = 51h    ---    = 55h
  112. ;       Grey - = 4ah    Grey + = 4eh    Ins   = 52h    ---    = 56h
  113. ;
  114. ;               47,  48,  49,  4a,  4b,  4c,  4d,  4e,  4f,  50,  51,  52,
  115. ;               53   54,  55,  56,  57,  58
  116. ttable:
  117.         DB      -1,  -1,  -1,  -1,  -1,  76,  -1,  -1,  -1,  -1,  -1,  -1
  118.         DB      -1,  -1,  -1,  -1, 133, 134
  119. shift_table:
  120.         DB      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1
  121.         DB      -1,  -1,  -1,  -1, 135, 136
  122. ctrl_table:
  123.         DB      -1, 141,  -1, 142,  -1, 143,  -1, 144,  -1, 145,  -1, 146
  124.         DB     147,  -1,  -1,  -1, 137, 138
  125. alt_table:
  126.         DB      -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1
  127.         DB      -1,  -1,  -1,  -1, 139, 140
  128.  
  129. old_int_9       DW      ?,?     ; space for old interrupt
  130.  
  131. start:
  132.         sti
  133.         push    ax      ; push the registers we use
  134.         push    bx
  135.         push    dx
  136.         push    ds
  137.         push    es
  138.  
  139.         in      al, kb_data_port        ; let's look at the waiting key
  140.  
  141.         cmp     al, 0fh         ; is it equal to tab?
  142.         je      special         ; yes, let's check for alt
  143.  
  144.         cmp     al, 1ah         ; is it less than "[{"?
  145.         jb      pop_out_9       ; yes, let regular int handle it
  146.         cmp     al, 1bh         ; is it less than "]}"?
  147.         jbe     special         ; yes, let's check for alt
  148.  
  149.         cmp     al, 27h         ; is it less than ";:"?
  150.         jb      pop_out_9       ; yes, let regular int handle it
  151.         cmp     al, 29h         ; is it less than "`~"?
  152.         jbe     special         ; yes, let's check for alt
  153.  
  154.         cmp     al, 33h         ; is it less than '<'?
  155.         jb      pop_out_9       ; yes, let regular int handle it
  156.         cmp     al, 35h         ; is it less than '?'?
  157.         jbe     special         ; yes, let's check for alt
  158.  
  159.         cmp     al, 47h         ; is it less than home?
  160.         jb      pop_out_9       ; yes, let regular int handle it
  161.         cmp     al, 80h         ; is it less than a break code?
  162.         jb      k1              ; yes, let's look at this key - a keypad key
  163.         ALIGN   2
  164. pop_out_9:
  165.         jmp     regular_int_9   ; default - let regular int 9 handle break codes
  166.                                 ; and other stuff
  167.  
  168. k1:
  169.         mov     dx, 0040h       ; segment of bios data area
  170.         mov     es, dx          ; put it in es
  171.         mov     dl, BYTE PTR es:kb_status  ; get shift status of alt & ctrl keys
  172.         test    dl, 0fh         ; & it with 0x0f to see if any shift keys down
  173.         jnz     k2              ; one of the shift keys is pressed - find it
  174.         mov     bx, OFFSET ttable       ; get offset of table
  175.         jmp     SHORT k5        ; no shift keys were down, translate normal keys
  176. k2:
  177.         test    dl, 03h                 ; are the left or right shift keys down?
  178.         jz      k3                      ; not pressed, must be a ctrl or an alt
  179.         mov     bx, OFFSET shift_table  ; get offset of shift table
  180.         jmp     SHORT k5
  181. k3:
  182.         test    dl, 04h                 ; is the control shift key down?
  183.         jz      k4                      ; not pressed, must be an alt
  184.         mov     bx, OFFSET ctrl_table   ; get offset of control table
  185.         jmp     SHORT k5
  186. k4:
  187.                                         ; the only shift key left is alt
  188.         mov     bx, OFFSET alt_table    ; get offset of alt table
  189.         ALIGN   2
  190. k5:
  191.         sub     al, 47h         ; normalize key to zero
  192.  
  193.         mov     dx, cs          ; put code segment in dx
  194.         mov     ds, dx          ; now transfer code segment to ds
  195.  
  196.         xlat                    ; table look up
  197.         cmp     al, -1          ; is it -1?
  198.         je      regular_int_9   ; yes, let regular interrupt 9 handle it
  199.  
  200.         mov     ah, al          ; put copy of character in ah
  201.         xor     al, al          ; zero out scan code - simulate extended key
  202.         jmp     SHORT k7
  203.         ALIGN   2
  204. special:
  205.         mov     dx, 0040h       ; segment of bios data area
  206.         mov     es, dx          ; put it in es
  207.         mov     dl, BYTE PTR es:kb_status  ; get shift status of alt & ctrl keys
  208.         test    dl, 08h         ; & it with 0x08 to see if the alt key is down
  209.         jnz     k6              ; alt key is down, let's do the special case
  210.         jmp     SHORT regular_int_9     ; otherwise goto regular interrupt 9
  211.         ALIGN   2
  212. k6:
  213.         mov     ah, al          ; put the scan code in ah
  214.         xor     al, al          ; zero out al
  215.         cmp     ah, 0fh         ; was Alt-Tab pressed?
  216.         jne     k7              ; no, nothing else needs to be done
  217.         mov     ah, 0a5h        ; extended code for tab is 0xa500
  218. ;
  219. ; We now have a key we want to emulate.  Put it in the keyboard buffer and
  220. ; end our interrupt.
  221. ;
  222. k7:
  223.         mov     bx, WORD PTR es:buffer_tail     ; get the end pointer to buffer
  224.         mov     dx, bx                          ; save in dx
  225.         inc     dx                              ; move to next word in list
  226.         inc     dx
  227.         cmp     dx, WORD PTR es:buffer_end      ; at end of buffer?
  228.         jnz     ck_full_kbd                     ; if no, continue
  229.         mov     dx, WORD PTR es:buffer_start    ; yes, reset to buffer start
  230.         ALIGN   2
  231.  
  232. ck_full_kbd:
  233.         cmp     dx, WORD PTR es:buffer_head     ; has the buffer wrapped?
  234.         jz      end_int_9       ; yes, kbd full - enable keyboard for next key
  235.         mov     WORD PTR es:[bx], ax    ; store simulated key into kbd buffer
  236.         mov     WORD PTR es:buffer_tail, dx     ; move the tail up for next key
  237.         ALIGN   2
  238.  
  239. end_int_9:
  240.         cli                     ; no interrupts now
  241.         mov     al, 20h         ; end of interrupt command
  242.         out     20h, al         ; send command to interrupt control port
  243.         sti                     ; enable interrupts - see IBM tech. ref. man.
  244.         in      al, kb_cntl_port        ; get char from control port
  245.         mov     ah, al                  ; save it in ah
  246.         or      al, 80h                 ; set bit 7
  247.         out     kb_cntl_port, al        ; output reset value
  248.         mov     al, ah                  ; send original value
  249.         jmp     SHORT $+2               ; take your time
  250.         out     kb_cntl_port, al        ; send it to enable keyboard
  251.         pop     es              ; restore registers
  252.         pop     ds
  253.         pop     dx
  254.         pop     bx
  255.         pop     ax
  256.         iret                    ; return from interrupt
  257. regular_int_9:
  258.         pop     es              ; restore registers
  259.         pop     ds
  260.         pop     dx
  261.         pop     bx
  262.         pop     ax
  263.         jmp     DWORD PTR old_int_9     ; no interrupt return - old one does it
  264.  
  265. ; ***********************************************************************
  266. ; prototype for _simulate_enh_kbd is
  267. ;
  268. ;               void far simulate_enh_kbd( int )
  269. ;
  270. ; The formal parameter is available on the stack.  Use the bp register to
  271. ; access it.
  272. ;
  273. ; Passing any non-zero value will make this function grab interrupt 9.
  274. ; Pass a zero to this function to restore the old interrupt 9.
  275. ;
  276. ; If this function were really clever, it would have a "unique" signature.
  277. ; Before "installing", it would check to see if it was already installed.
  278. ; Similarly, before "uninstalling", this function would check to make sure
  279. ; it was installed so it wouldn't uninstall the regular interrupt 9
  280. ; handler by accident.  What the hell, live dangerously.
  281. ;
  282. ; ***********************************************************************
  283.  
  284. initialize:
  285.         push    bp
  286.         mov     bp, sp
  287.  
  288.         mov     dx, [bp+6]      ; put the parameter in dx
  289.  
  290.         push    ds
  291.         ASSUME  es:_TEXT,ds:_TEXT
  292.         mov     ax, cs          ; put cs in ds
  293.         mov     es, ax
  294.         mov     ds, ax
  295.  
  296.         cmp     dx, 0           ; 'NULL' character unhooks interrupt 9
  297.         je      restore_9       ; any non NULL character grabs interrupt 9
  298. grab_9:
  299.         mov     ax, 3509h       ; get old interrupt 9 location
  300.         int     21h             ; call MSDOS to get it
  301.         mov     WORD PTR old_int_9, bx          ; save old int 9 offset
  302.         mov     WORD PTR old_int_9+2, es        ; save old int 9 segment
  303.  
  304.         mov     dx, OFFSET start        ; get new offset of int 9
  305.         mov     ax, 2509h               ; use function 25 so int 9 points
  306.         int     21h                     ;  to my routine
  307.         jmp     SHORT get_out           ; continue with editor
  308.  
  309. restore_9:
  310.         mov     dx, WORD PTR old_int_9          ; get offset of old int 9
  311.         mov     ax, WORD PTR old_int_9+2        ; get segment of old int 9
  312.         mov     ds, ax                          ;  put segment in ds
  313.         mov     ax, 2509h                       ; restore old int 9
  314.         int     21h
  315.  
  316. get_out:
  317.         pop     ds              ; clean up
  318.         pop     bp
  319.         retf
  320. _simulate_enh_kbd       endp
  321. _TEXT   ends
  322.         end
  323.